﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Security.Principal;
using System.Web;
using System.Web.Mvc;
using SnippetBox.Core.Common.Mvc.Validation;
using SnippetBox.Core.Data.Service;

namespace SnippetBox.Core.Data.Models {
    public class User : IPrincipal, IDeletable, IValidatableObject {
        public User(string username, string passwordHashed) {
            Username = username;
            PasswordHashed = passwordHashed;
            DateCreated = DateTime.Now;
        }

        public User() { }

        public int UserId { get; set; }
        [Required, MaxLength(100), Remote("UsernameFree", "Users", "Manage", AdditionalFields = "UserId", ErrorMessage = "Username already taken.")]
        public string Username { get; set; }
        [MaxLength(100)]
        public string PasswordHashed { get; set; }
        [RegularExpressionAttribute(Regexps.EMAIL, ErrorMessage = "Invalid email address")]
        public string Email { get; set; }
        [MaxLength(15)]
        public string TwitterUsername { get; set; }
        [MaxLength(100)]
        public string Website { get; set; }
        [UIHint("RelativeDate")]
        public DateTime DateCreated { get; set; }
        [UIHint("Snippet")]
        public virtual ICollection<Snippet> Snippets { get; set; }
        [UIHint("Snippet")]
        public virtual ICollection<Favorite> Favorites { get; set; }
        public bool IsDeleted { get; set; }

        public string Link {
            get {
                UrlHelper url = new UrlHelper(HttpContext.Current.Request.RequestContext);
                return url.RouteUrl("User-Details", new { username = Username });
            }
        }

        [Column("Role")]
        public int InternalRole { get; set; }

        [NotMapped]
        public Role Role {
            get { return (Role)InternalRole; }
            set { InternalRole = (int)value; }
        }

        public bool IsInRole(string role) {
            return Role >= RoleParser.Parse(role);
        }

        public bool IsInRole(Role role) {
            return Role >= role;
        }

        public IIdentity Identity {
            get { return new GenericIdentity(Username); }
        }

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
            UserService userService = new UserService();

            if (userService.UsernameExists(Username, UserId))
                yield return new ValidationResult("Username already taken.", new[] { "Username" });
        }
    }
}